// @flow

function sum(a: number, b: number) {
  return a + b;
}

sum(1, 2);
// sum(1, '2')

/**
 * 类型推断
 */

function square(a) {
  return a * a;
}

square(2);
// square('1')

/**
 * 类型注解
 */

let a: number = 1;
// a = 'a'
a = 2;

/**
 * 原始类型
 */

// string
// number
// boolean
// null
// void(undefined)
// symbol

/**
 * 数组类型
 */

// const arr: Array<number> = [1, 2, 3, '4']
const arr: Array<number> = [1, 2, 3, 4];
const arr2: number[] = [1, 2, 3, 4];
const arr3: [string, number] = ['1', 2]; // 元组

/**
 * 对象类型
 */

let obj: {
  a: number,
  b: string,
  c?: number[],
  [string]: string,
} = {
  a: 1,
  b: '2',
  c: [1, 2, 3],
  d: '4',
};

/**
 * 函数类型
 */
function foo(callback: (number, string) => void) {
  callback(100, '200');
}
foo((a, b) => {
  console.log('foo callback:', a, b);
  // return 1
});

/**
 * 特殊类型（字面量类型）
 */
const myType: 'success' | 'fail' | 'padding' = 'success';
type StringOrNumber = string | number;
const myType2: StringOrNumber = '123';
// maybe 类型
const myType3: ?number = undefined;
const myType4: number | void | null = undefined;
// NOTE myType3 等价 myType4
// mixed,any 类型
let myType5: mixed = '123';
myType5 = 123;
let myType6: any = 123;
myType6 = '123';

// function passMixed1(x: mixed) {
//   x.substr(1)
//   x * x
// }
// error: Cannot call `x.substr` because property `substr` is missing in  mixed [1].
// error: Cannot perform arithmetic operation because  mixed [1] is not a number.
function passMixed2(x: mixed) {
  if (typeof x === 'string') {
    x.substr(1);
  }
  if (typeof x === 'number') {
    x * x;
  }
}
function passAny(x: any) {
  x.substr(1);
  x * x;
}
// NOTE mixed仍然是强类型 any为弱类型

/**
 * 运行环境api
 */
const element: ?HTMLElement = document.getElementById('root');
